/*******************************************************************************
 * Copyright 2011 @ Kapil Viren Ahuja
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 ******************************************************************************/
package com.kapil.framework.lang;

/**
 * Provides utility methods for {@link String}.
 * 
 */
public final class StringUtils
{
    private StringUtils()
    {
    }


    /**
     * Determines if a text string is <em>blank</em>. A string is said to be <em>blank</em> when it does not contain any
     * characters or does not show anything when printed. Therefore, a text string with only white spaces (spaces, tabs,
     * newline characters and carriage returns) will be a <em>blank</em> string.
     * 
     * @param value Text string to be tested.
     * @return True if the string is <em>blank</em>, false otherwise.
     */
    public static boolean isBlank(String value)
    {
        return value == null || value.trim().equals("");
    }


    /**
     * Determines if a text string is not <em>blank</em>.
     * 
     * @see StringUtils#isBlank(String)
     * 
     * @param value Text string to be tested.
     * @return True if the string is <em>blank</em>, false otherwise.
     */
    public static boolean isNotBlank(String value)
    {
        return !isBlank(value);
    }


    /**
     * Replaces all occurrences of a token in a sentence with a String provided as replacement. In addition, it also
     * wraps the replacement message with a provided prefix and suffix.
     * 
     * @see StringUtils#replaceToken(String, String, String, char, char)
     * 
     */
    public static String replaceTokens(String sentence, String token, String[] replacements, char wrapperPrefix, char wraperSuffix)
    {
        String result = sentence; // NOPMD

        if (isNotBlank(sentence) && replacements != null)
        {
            for (String replacement : replacements)
            {
                result = replaceToken(result, token, replacement, wrapperPrefix, wraperSuffix);
            }
        }

        return result;
    }


    /**
     * Replaces all occurrences of a token in a sentence with a String provided as replacement.
     * 
     * 
     * @param sentence a {@link String} in which the token has to be searched and replaced.
     * @param token a {@link String} token that needs to be replaced.
     * @param replacement a {@link String} the message that will replace the token.
     * 
     * @return a {@link String} where all the occurrences of the token have been replaced.
     * 
     */
    public static String replaceTokens(String sentence, String token, String[] replacements)
    {
        String result = sentence;

        if (isNotBlank(sentence) && replacements != null)
        {
            for (String replacement : replacements)
            {
                result = replaceToken(result, token, replacement);
            }
        }

        return result;
    }


    public static String replaceTokens(String sentence, String token, String replacement)
    {
        if (!hasLength(sentence) || !hasLength(token) || replacement == null)
        {
            return sentence;
        }

        StringBuilder sb = new StringBuilder();
        int pos = 0; // our position in the old string
        int index = sentence.indexOf(token); // the index of an occurrence we've found, or -1
        int patLen = token.length();


        while (index >= 0)
        {
            sb.append(sentence.substring(pos, index)); // append the string before the index
            sb.append(replacement); // append the replacement string
            pos = index + patLen; // change the position based on changed string
            index = sentence.indexOf(token, pos); // update the index to next occurrence;
        }

        // append the remainder of the string; after the last match
        sb.append(sentence.substring(pos));

        return sb.toString();
    }


    /**
     * Replaces a single and first occurrence of a token in a sentence with a String provided as replacement. In
     * addition, it also wraps the replacement message with a provided prefix and suffix. For example:
     * 
     * <code>
     *  Consider a sentence: "I am an error. The issue with me is ##"
     *  If we want to replace a token ## with replacement text: "Number formatting error".
     *  The resultant string will be: "I am an error. The issue with me is [Number formatting error]" 
     * </code>
     * 
     * @param sentence a {@link String} in which the token has to be searched and replaced.
     * @param token a {@link String} token that needs to be replaced.
     * @param replacement a {@link String} the message that will replace the token.
     * @param wrapperPrefix a {@link String} prefix for the message.
     * @param wraperSuffix a {@link String} suffix for the message.
     * 
     * @return a {@link String} where the first occurrence of the token is replaced.
     * 
     */
    public static String replaceToken(String sentence, String token, String replacement, char wrapperPrefix, char wraperSuffix)
    {
        return isBlank(sentence) ? sentence : sentence.replaceFirst(token, wrapperPrefix + replacement + wraperSuffix);
    }


    /**
     * Replaces a single and first occurrence of a token in a sentence with a String provided as replacement. For
     * example:
     * 
     * <code>
     *  Consider a sentence: "I am an error. The issue with me is ##"
     *  If we want to replace a token ## with replacement text: "Number formatting error".
     *  The resultant string will be: "I am an error. The issue with me is Number formatting error" 
     * </code>
     * 
     * @param sentence a {@link String} in which the token has to be searched and replaced.
     * @param token a {@link String} token that needs to be replaced.
     * @param replacement a {@link String} the message that will replace the token.
     * @param wrapperPrefix a {@link String} prefix for the message.
     * @param wraperSuffix a {@link String} suffix for the message.
     * 
     * @return a {@link String} where the first occurrence of the token is replaced.
     * 
     */
    public static String replaceToken(String sentence, String token, String replacement)
    {
        return isBlank(sentence) ? sentence : sentence.replaceFirst(token, replacement);
    }


    /**
     * Finds if the {@link String} is a not 0-length {@link String}. If the passed {@link String} is <code>null</code>,
     * it returns <code>FALSE</code>.
     * 
     * @param a {@link String} that needs to be evaluated
     * @return <code>true</code> if {@link String} has a length > 0, else <code>false</code>
     */
    public static boolean hasLength(String str)
    {
        return hasLength((CharSequence) str);
    }


    /**
     * 
     * Finds if the {@link CharSequence} is a not 0-length {@link CharSequence}. If the passed {@link CharSequence} is <code>null</code>,
     * it returns <code>FALSE</code>.
     * 
     * @param a {@link CharSequence} that needs to be evaluated
     * @return <code>true</code> if {@link CharSequence} has a length > 0, else <code>false</code>
     */
    public static boolean hasLength(CharSequence str)
    {
        return (str != null && str.length() > 0);
    }
}
